<?php
class Controller extends Object {
	var $name = null;

	var $action = null;

	var $params = array();

	var $data = array();

	var $paginate = array('limit' => 20, 'page' => 1);

	var $layoutPath = null;

	var $viewVars = array();

//	var $modelNames = array();

//	var $base = null;

	var $layout = 'default';

	var $autoRender = true;

	var $autoLayout = true;

	var $ext = VIEW_EXT;

	var $viewPath = null;

	var $parameters = null;

//	var $output = null;

//	var $cacheAction = false;
/**
 * Holds all params passed and named.
 *
 * @var mixed
 * @access public
 */
	var $passedArgs = array();

	var $methods = array();


	/**
	 * コンストラクタ
	 */
	function __construct(&$dispacher) {
		if(!is_object($dispacher)){
			return;
		}
		$this->action = $dispacher->action;
		$this->parameters = $dispacher->parameters;
		$this->name = get_class($this);
		$this->viewPath = strtolower(substr($this->name, 0, -(strlen('Controller'))));

		$thisMethods = get_class_methods($this);
		$parentMethods = get_class_methods('Controller');

		foreach ($thisMethods as $key => $value) {
			$thisMethods[$key] = strtolower($value);
		}

		foreach ($parentMethods as $key => $value) {
			$parentMethods[$key] = strtolower($value);
		}
		$this->methods = array_diff($thisMethods, $parentMethods);
		parent::__construct();
	}

	function redirect($url) {
		$this->autoRender = false;

		if (function_exists('session_write_close')) {
			session_write_close();
		}

		if ($url !== null) {
			header('Location: ' . Router::url($url, true));
		}
		exit(0);
	}

	function set($one, $two = null) {
		$data = array();

		if (is_array($one)) {
			if (is_array($two)) {
				$data = array_combine($one, $two);
			} else {
				$data = $one;
			}
		} else {
			$data = array($one => $two);
		}

		foreach ($data as $name => $value) {
			if ($two === null && is_array($one)) {
				$this->viewVars[Inflector::variable($name)] = $value;
			} else {
				$this->viewVars[$name] = $value;
			}
		}
	}
/**
 * Internally redirects one action to another. Examples:
 *
 * setAction('another_action');
 * setAction('action_with_parameters', $parameter1);
 *
 * @param string $action The new action to be redirected to
 * @param mixed  Any other parameters passed to this method will be passed as
 *               parameters to the new action.
 * @return mixed Returns the return value of the called action
 * @access public
 */
	function setAction($action) {
		$this->action = $action;
		$args = func_get_args();
		unset($args[0]);
		return call_user_func_array(array(&$this, $action), $args);
	}
/**
 * Instantiates the correct view class, hands it its data, and uses it to render the view output.
 *
 * @param string $action Action name to render
 * @param string $layout Layout to use
 * @param string $file File to use for rendering
 * @return string Full output string of view contents
 * @access public
 * @link http://book.cakephp.org/view/428/render
 */
	function render($action) {
//		$this->beforeRender();

//		$View =& new $viewClass($this);
		$view = new View($this);

		if($this->autoRender){
			$actionFullPath = VIEWS.$this->viewPath.DS.$action.VIEW_EXT;
			$output = $view->render($actionFullPath);
			if($this->autoLayout){
				$output = $view->renderLayout($output);
			}
		}
		return $output;
	}

	function beforeFilter() {
	}

	function beforeRender() {
	}

	function afterFilter() {
	}


	function execute(){
		// アクションメソッドがなかったら戻る（エラーではない）
		if(!in_array(strtolower($this->action), $this->methods)){
			return;
		}
		$params = array();
		if(is_array($this->parameters)){
			$params = $this->parameters;
		}

		switch (count($params)){
			case 0:
				$this->{$this->action}();
				break;
			case 1:
				$this->{$this->action}($params[0]);
				break;
			case 2:
				$this->{$this->action}($params[0], $params[1]);
				break;
			case 3:
				$this->{$this->action}($params[0], $params[1], $params[2]);
				break;
			case 4:
				$this->{$this->action}($params[0], $params[1], $params[2], $params[3]);
				break;
			case 5:
				$this->{$this->action}($params[0], $params[1], $params[2], $params[3], $params[4]);
				break;
		}
	}
}